package player

import (
	"context"
	"gitee.com/xcy871622040/gameframe/cluster"
	"gitee.com/xcy871622040/gameframe/cluster/rpcx"
	"github.com/smallnest/rpcx/client"
	"github.com/smallnest/rpcx/server"
	"google.golang.org/protobuf/proto"
	"net"
	"net/url"
)

var (
	xServer *server.Server
	xClient rpcx.XClient
)

// InitAgent 初始化代理
func InitAgent(svr *server.Server) {
	xServer = svr
	xClient = rpcx.NewXClient(
		cluster.App().Runtime.Discovery,
		rpcx.WithFailMode(client.Failtry),
		rpcx.WithSelectMode(client.SelectByUser, func(customized *rpcx.Customized) {
			customized.SetFilterFunc(func(ctx context.Context, service, method string, node url.Values) bool {
				return true
			})
		}),
	)
}

type Agent struct {
	conn net.Conn
}

// New 创建一个代理
func New(ctx context.Context) *Agent {
	if val := ctx.Value(server.RemoteConnContextKey); val != nil {
		return &Agent{conn: val.(net.Conn)}
	} else {
		return &Agent{conn: nil}
	}
}

// Call 远程调用
func (a *Agent) Call(ctx context.Context, servicepath, method string, args interface{}, reply interface{}) error {
	return xClient(servicepath).Call(ctx, method, args, reply)
}

// Send 通过proto序列化后发送
func (a *Agent) Send(ctx context.Context, servicepath, method string, args proto.Message) error {
	if a.conn == nil { // 其他节点通过rpcx发送通知
		if _, err := xClient(servicepath).Go(ctx, servicepath, method, args, nil); err != nil {
			return err
		}
		return nil
	}

	// 本节点 通过 rpcx双向通信发送通知
	if msg, err := proto.Marshal(args); err != nil {
		return err
	} else {
		return a.SendByte(servicepath, method, map[string]string{"SetSerializeType": "protobuf"}, msg)
	}
}

// SendByte 发送序列化完毕的二进制流
func (a *Agent) SendByte(path, method string, matedata map[string]string, data []byte) error {
	return xServer.SendMessage(a.conn, path, method, matedata, data)
}
